package com.huai.jt1078.handler;

import com.huai.jt1078.entity.AudioInfo;
import com.huai.jt1078.entity.VisualAudio;
import com.huai.jt1078.enums.DataType;
import com.huai.jt1078.utils.ByteUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author xingkong
 * @program jt1078
 * @description 消息编解码处理器
 * @date 2021-09-04 10:49
 **/
@ChannelHandler.Sharable
@Slf4j
@Component
public class MessageDecoderHandler extends MessageToMessageCodec<ByteBuf,AudioInfo> {

    private byte[] HEADER_BYTES = new byte[]{48,49,99,100,-127};

    /**
     * 数据加密 这里仅针对音频加密（我们也不需要下发其他消息下去）
     * @param ctx 上下文
     * @param out  输出
     * @param audioInfo 回传的音频数据
     * @author xingkong
     * @date 2021-09-16 10:24
     */
    @Override
    protected void encode(ChannelHandlerContext ctx, AudioInfo audioInfo, List<Object> out) throws Exception{
        ByteBuf buffer = ctx.alloc().buffer();
        // 【5】
        buffer.writeBytes(HEADER_BYTES);
        // 第一位是1 表示是完整的帧边界
        buffer.writeByte(audioInfo.getLoadType() | 0x80);
        // 序号 【2】
        buffer.writeShort(audioInfo.getSequence());
        // 根据ctx获取SIM卡号和通道号

        byte[] simNos = ByteUtil.setBcd(audioInfo.getSimNo(),6);
        // 【6】
        buffer.writeBytes(simNos);
        // 【1】
        buffer.writeByte(audioInfo.getChannelNo());
        // 这里高四位是音频 第四位是0000原子包 【1】
        buffer.writeByte(DataType.AUDIO.getType()<<4);
        // 设置时间戳
        buffer.writeLong(audioInfo.getTimeStamp());

        // 这里没有last frame Interval 和last frame interval

        byte[] msg = audioInfo.getData();
        // 写入数据长度
        buffer.writeShort(msg.length);
        // 写入数据
        buffer.writeBytes(msg);
        // 收集数据
        out.add(buffer);
    }

    /**
     * 消息解密
     *
     * @param channelHandlerContext 上下文
     * @param byteBuf               收到的byteBuf
     * @param list                  收集器
     * @throws Exception 异常
     */
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        // 前8个字符都是固定字符 0x30 0x31 0x63 0x64 2001 MPT 和包序号 这里直接选择跳过
        byte[] bytes = new byte[5];
        byteBuf.readBytes(bytes);
        // 负载类型
        byte mpt = byteBuf.readByte();
        int pt = mpt & 0x7f;
        // 包序号
        int sequence = byteBuf.readShort();

        // 这里读取SIM卡号
        StringBuilder simBuilder = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            simBuilder.append(ByteUtil.getBcd(byteBuf.readByte()));
        }
        // 获取sim卡号
        String simNo = simBuilder.toString();

        VisualAudio visualAudio = VisualAudio.builder().loadType(pt).sequence(sequence).simNo(simNo)
                .channelNo(byteBuf.readByte() & 0xff).build();
        byte dataTypeAndTag = byteBuf.readByte();
        visualAudio.setDataType((dataTypeAndTag >> 4) & 0x0f);
        visualAudio.setSubTag(dataTypeAndTag & 0x0f);

        // 如果当前类型不是透传 则有时间戳字段
        if (!DataType.PASS.getType().equals(visualAudio.getDataType())) {
            visualAudio.setTimeStamp(byteBuf.readLong());
        }

        // 如果是视频类型
        if (DataType.getVideoTypes().contains(visualAudio.getDataType())) {
            visualAudio.setLastKeyFrame(byteBuf.readShort() & 0xff);
            visualAudio.setLastFrame(byteBuf.readShort() & 0xff);
        }

        // 获取数据长度
        visualAudio.setDataLength((int)byteBuf.readShort());
        // 获取数据体
        byte[] data = new byte[visualAudio.getDataLength()];
        byteBuf.readBytes(data);
        visualAudio.setData(data);

        if (visualAudio.getData().length != visualAudio.getDataLength()) {
            log.error("数据异常，数据不匹配 数据长度：{}  真实数据长度:{}", visualAudio.getDataLength(), visualAudio.getData().length);
        }

        list.add(visualAudio);
    }
}
